package com.sharer.last.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sharer.last.base.enums.BusinessExceptionCode;
import com.sharer.last.base.enums.ExceptionPrefixParamEnum;
import com.sharer.last.base.exception.BusinessException;
import com.sharer.last.base.model.PageVO;
import com.sharer.last.base.support.QueryCondition;
import com.sharer.last.base.utils.CollectionUtil;
import com.sharer.last.base.utils.ConvertUtil;
import com.sharer.last.base.utils.StringUtil;
import com.sharer.last.mapper.TagMapper;
import com.sharer.last.model.dto.tag.TagChangeDTO;
import com.sharer.last.model.dto.tag.TagQueryDTO;
import com.sharer.last.model.po.BlogTagPO;
import com.sharer.last.model.po.TagPO;
import com.sharer.last.model.vo.tag.TagVO;
import com.sharer.last.service.BlogTagService;
import com.sharer.last.service.TagService;
import com.sharer.last.utils.BeanUtil;
import com.sharer.last.utils.CommonUtil;
import com.sharer.last.wrapper.TagWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 博客标签业务层实现
 *
 * @ClassName TagServiceImpl
 * @Author wangjin
 * @Date 2023/5/5 20:46
 * @Description
 * @Version 1.0
 */
@Service
public class TagServiceImpl extends ServiceImpl<TagMapper, TagPO> implements TagService {
    @Resource
    TagMapper tagMapper;

    @Resource
    TagWrapper tagWrapper;

    @Resource
    BlogTagService blogTagService;

    private LambdaQueryWrapper<TagPO> buildQueryWrapper(TagQueryDTO queryDTO) {
        LambdaQueryWrapper<TagPO> qw     = new LambdaQueryWrapper<>();
        qw.orderByAsc(TagPO::getId);
        return qw;
    }

    /**
     * 根据tag名称查找数据
     *
     * @param tagName 标签名称
     * @return
     */
    @Override
    public TagPO getByTagName(String tagName) {
        LambdaQueryWrapper<TagPO> qw = new LambdaQueryWrapper<>();
        if (StringUtil.isBlank(tagName)) {
            throw new BusinessException(BusinessExceptionCode.NAME_IS_BLANK, ExceptionPrefixParamEnum.TAG);
        }
        qw.eq(TagPO::getTagName, tagName);
        return this.getOne(qw, false);
    }

    /**
     * 根据id查询数据
     *
     * @param id
     * @return
     */
    @Override
    public TagVO findById(Long id) {
        TagPO tagPO = this.getById(id);
        if (tagPO == null) {
            throw new BusinessException(BusinessExceptionCode.DATA_IS_EMPTY, ExceptionPrefixParamEnum.TAG);
        }
        return tagWrapper.entityVO(tagPO);
    }

    /**
     * 根据id集合查询数据
     *
     * @param tagIdList
     * @return
     */
    @Override
    public List<TagPO> queryListByIds(List<Long> tagIdList) {
        LambdaQueryWrapper<TagPO> qw = new LambdaQueryWrapper<>();
        qw.in(TagPO::getId, tagIdList);
        return this.list(qw);
    }

    /**
     * 分页查询
     *
     * @param queryDTO
     * @return
     */
    @Override
    public PageVO<TagVO> selectListByPage(TagQueryDTO queryDTO) {
        LambdaQueryWrapper<TagPO> qw   = this.buildQueryWrapper(queryDTO);
        IPage<TagPO>              page = this.page(QueryCondition.getPage(queryDTO.getPage()), qw);
        return tagWrapper.toPageVO(page);
    }

    /**
     * 查询所有标签
     *
     * @return
     */
    @Override
    public List<TagVO> selectAllList() {
        List<TagPO> list = this.list();
        if (CollectionUtil.isNotEmpty(list)) {
            return tagWrapper.listVO(list);
        }
        return new ArrayList<>();
    }

    /**
     * 根据便签名称集合查询集合
     *
     * @param tagList
     * @return
     */
    @Override
    public List<TagPO> selectListByTagNames(List<String> tagList) {
        List<TagPO> list = new ArrayList<>();
        if (CollectionUtil.isEmpty(tagList)) {
            return list;
        }
        LambdaQueryWrapper<TagPO> qw = new LambdaQueryWrapper<>();
        qw.in(TagPO::getTagName, tagList);
        list = this.list(qw);
        return list;
    }

    /**
     * 创建标签
     *
     * @param blogId  博客id
     * @param tagList 标签
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void createTag(Long blogId, List<String> tagList) {
        if (CollectionUtil.isNotEmpty(tagList)) {
            // 获取 新增标签集合
            List<TagPO>  tagPOList   = this.selectListByTagNames(tagList);
            List<String> isExistList = tagPOList.stream().map(TagPO::getTagName).collect(Collectors.toList());
            List<String> addList     = CommonUtil.differenceList(tagList, isExistList);
            // 标签新增
            if (CollectionUtil.isNotEmpty(addList)) {
                List<TagPO> saveList = new ArrayList<>();
                for (String tagName : addList) {
                    saveList.add(TagPO.builder().tagName(tagName).build());
                }
                if (!this.saveBatch(saveList)) {
                    throw new BusinessException(BusinessExceptionCode.DATA_INSERT_FAIL, ExceptionPrefixParamEnum.TAG);
                }
            }
            // 博客和标签的关联关系新增
            List<BlogTagPO> blogTagPOList = new ArrayList<>();// 博客便签关联集合
            List<TagPO>     tagNewList    = this.selectListByTagNames(tagList);
            for (TagPO tagPO : tagNewList) {
                blogTagPOList.add(BlogTagPO.builder().blogId(blogId).tagId(tagPO.getId()).build());
            }
            // 博客和便签关联关系删除
            blogTagService.deleteByBlogId(blogId);
            // 博客和便签关联关系新增
            if (!blogTagService.saveBatch(blogTagPOList)) {
                throw new BusinessException(BusinessExceptionCode.DATA_INSERT_FAIL, ExceptionPrefixParamEnum.BLOG_TAG);
            }
        }
    }

    /**
     * 创建标签
     *
     * @param dto 标签参数封装
     */
    @Override
    public void createTag(TagChangeDTO dto) {
        String tagName = dto.getTagName();
        TagPO  tag     = getByTagName(tagName);
        if (tag != null) {
            throw new BusinessException(BusinessExceptionCode.DATA_IS_EXIST, ExceptionPrefixParamEnum.TAG);
        }
        TagPO tagPO = BeanUtil.copy(dto, TagPO.class);
        if (!this.save(tagPO)) {
            throw new BusinessException(BusinessExceptionCode.DATA_INSERT_FAIL, ExceptionPrefixParamEnum.TAG);
        }
    }

    /**
     * 标签更新
     *
     * @param dto
     */
    @Override
    public void updateTag(TagChangeDTO dto) {
        Long id = dto.getId();
        if (ConvertUtil.toInt(id) < 1) {
            throw new BusinessException(BusinessExceptionCode.ID_IS_NULL, ExceptionPrefixParamEnum.TAG);
        }
        String tagName = dto.getTagName();
        TagPO  tag     = getById(id);
        if (tag != null && !tag.getTagName().equals(tagName)) {
            throw new BusinessException(BusinessExceptionCode.DATA_IS_EXIST, ExceptionPrefixParamEnum.TAG);
        }
        LambdaQueryWrapper<TagPO> qw = new LambdaQueryWrapper<>();
        qw.eq(TagPO::getId, id);
        TagPO tagPO = BeanUtil.copy(dto, TagPO.class);
        tagPO.setId(null);
        if (!this.update(tagPO, qw)) {
            throw new BusinessException(BusinessExceptionCode.DATA_UPDATE_FAIL, ExceptionPrefixParamEnum.TAG);
        }
    }


    /**
     * 根据id删除数据
     *
     * @param id 标签id
     */
    @Override
    public void deleteTagById(Long id) {
        // 校验标签是否存在
        TagPO tagPO = this.getById(id);
        if (tagPO == null) {
            throw new BusinessException(BusinessExceptionCode.DATA_IS_EMPTY, ExceptionPrefixParamEnum.TAG);
        }
        // 校验标签和博客是否存在关联
        if (blogTagService.getBlogNumByTagId(id) > 0) {
            throw new BusinessException(BusinessExceptionCode.TAG_HAS_BLOG_EXIST_RELATEDNESS);
        }
        // 删除标签
        if (!this.removeById(id)) {
            throw new BusinessException(BusinessExceptionCode.DATA_REMOVE_FAIL, ExceptionPrefixParamEnum.TAG);
        }
    }

}
